'use strict';

const fs = require("fs")
const path = require("path")
const inquirer = require("inquirer")
const semver = require("semver")
const fse = require("fs-extra")
const ejs = require("ejs") // 模版编译
const glob = require("glob") // 文件路径匹配 需要编译文件
const userHome = require("user-home")
//  初始化项目
const Command = require("@wss-cli-dev/command")
const log = require("@wss-cli-dev/log")
const Package = require("@wss-cli-dev/package")
const { spinnerStart, sleep, execAsync } = require('@wss-cli-dev/utils');
const { getProjectTemplate } = require("./template")

const TYPE_PROJECT = 'project';
const TYPE_COMPONENT = 'component';

const TEMPLATE_TYPE_NORMAL = 'normal';
const TEMPLATE_TYPE_CUSTOM = 'custom';

const WHITE_COMMAND = ['npm', 'cnpm'];

class InitCommand extends Command {

  // 初始化 参数
  init() {
    this.projectName = this._argv[0] || ""
    this.force = !!this._cmd.force
    log.verbose("projectName", this.projectName)
    log.verbose("force", this.force)
  }
  // ***** 初始化操作
  async exec() {
    try {
      // 1. 准备
      const projectInfo = await this.prepare()
      // 2. 下载
      if (projectInfo) {
        log.verbose("projectinfo", projectInfo)
        this.projectInfo = projectInfo;
        await this.downloadTemplate();
        // 3. 安装
        await this.installTemplate()
      }

    } catch (error) {
      log.error(error.message)
    }

  }
  //  安装模版信息
  async prepare() {
    const template = getProjectTemplate;
    if (!template || template.length === 0) {
      throw new Error('项目模板不存在');
    }
    this.template = template
    // 判断当前目录是否为空
    const localPath = process.cwd()
    if (!this.isDirEmpty(localPath)) {
      // 是否强制更新
      let ifContinue = false
      if (!this.force) {
        ifContinue = (await inquirer.prompt({
          type: "confirm",
          name: "ifContinue",
          default: false,
          message: "当前文件不为空，是否继续创建项目？",
        })).ifContinue
        if (!ifContinue) {
          return
        }
      }
      if (ifContinue || this.force) {
        const { confirmDelete } = await inquirer.prompt({
          type: 'confirm',
          name: 'confirmDelete',
          default: false,
          message: '是否确认清空当前目录下的文件？',
        });
        if (confirmDelete) {
          fse.emptyDirSync(localPath)
        }
      }
    }
    return this.getProjectInfo()
  }
  // 执行模版信息
  async getProjectInfo() {
    function isValidName(v) {
      return /^[a-zA-Z]+([-][a-zA-Z][a-zA-Z0-9]*|[_][a-zA-Z][a-zA-Z0-9]*|[a-zA-Z0-9])*$/.test(v);
    }
    let projectInfo = {};
    // const { type } = await inquirer.prompt({
    //   type: 'list',
    //   name: 'type',
    //   default: TYPE_PROJECT,
    //   message: '请选择初始化类型',
    //   choices: [{
    //     name: "项目",
    //     value: TYPE_PROJECT
    //   }, {
    //     name: "组件",
    //     value: TYPE_COMPONENT
    //   }]
    // })
    let isProjectNameValid = false;
    if (isValidName(this.projectName)) {
      isProjectNameValid = true;
      projectInfo.projectName = this.projectName;
    }
    console.log(projectInfo);
    // 1. 选择 创建项目或组件
    const { type } = await inquirer.prompt({
      type: 'list',
      name: 'type',
      message: '请选择初始化类型',
      default: TYPE_PROJECT,
      choices: [{
        name: '项目',
        value: TYPE_PROJECT,
      }, {
        name: '组件',
        value: TYPE_COMPONENT,
      }],
    });
    log.verbose('type', type);
    this.template = this.template.filter(template =>
      template.tag.includes(type));
    console.log(this.template);
    const title = type === TYPE_PROJECT ? '项目' : '组件';
    const projectNamePrompt = {
      type: 'input',
      name: 'projectName',
      message: `请输入${title}名称`,
      default: '',
      validate: function (v) {
        const done = this.async();
        setTimeout(function () {
          // 1.首字符必须为英文字符
          // 2.尾字符必须为英文或数字，不能为字符
          // 3.字符仅允许"-_"
          if (!isValidName(v)) {
            done(`请输入合法的${title}名称`);
            return;
          }
          done(null, true);
        }, 0);
      },
      filter: function (v) {
        return v;
      },
    };
    const projectPrompt = [];
    if (!isProjectNameValid) {
      projectPrompt.push(projectNamePrompt);
    }
    projectPrompt.push({
      type: 'input',
      name: 'projectVersion',
      message: `请输入${title}版本号`,
      default: '1.0.0',
      validate: function (v) {
        const done = this.async();
        setTimeout(function () {
          if (!(!!semver.valid(v))) {
            done('请输入合法的版本号');
            return;
          }
          done(null, true);
        }, 0);
      },
      filter: function (v) {
        if (!!semver.valid(v)) {
          return semver.valid(v);
        } else {
          return v;
        }
      },
    },
      {
        type: 'list',
        name: 'projectTemplate',
        message: `请选择${title}模板`,
        choices: this.createTemplateChoice(),
      });
    if (type === TYPE_PROJECT) {
      //   // 项目信息
      const project = await inquirer.prompt(projectPrompt);
      projectInfo = {
        ...projectInfo,
        type,
        ...project
      }

    }
    // if (type===TYPE_COMPONENT) {
    //   const descriptionPrompt = {
    //     type: 'input',
    //     name: 'componentDescription',
    //     message: '请输入组件描述信息',
    //     default: '',
    //     validate: function (v) {
    //       const done = this.async();
    //       setTimeout(function () {
    //         if (!v) {
    //           done('请输入组件描述信息');
    //           return;
    //         }
    //         done(null, true);
    //       }, 0);
    //     },
    //   };
    //   projectPrompt.push(descriptionPrompt);
    //   const component = await inquirer.prompt(projectPrompt);
    // }
    // console.log(12);
    // 生成classname
    if (projectInfo.projectName) {
      projectInfo.name = projectInfo.projectName;
      projectInfo.className = require('kebab-case')(projectInfo.projectName).replace(/^-/, '');
    }
    console.log(projectInfo);
    // if (projectInfo.projectVersion) {
    //   projectInfo.version = projectInfo.projectVersion;
    // }
    // if (projectInfo.componentDescription) {
    //   projectInfo.description = projectInfo.componentDescription;
    // }


    return projectInfo;
  }
  isDirEmpty(localPath) {
    const filelist = fs.readdirSync(localPath)
    filelist.filter(file => (
      !file.startsWith(".") && ["node_modules"].indexOf(file) < 0
    ))
    return !filelist || filelist.length <= 0
  }
  async downloadTemplate() {
    // 1. 通过项目模版 api 获取模版信息
    const { projectTemplate } = this.projectInfo;
    const templateInfo = this.template.find(item => item.npmName === projectTemplate)
    const targetPath = path.resolve(userHome, ".wss-cli-dev", "template")
    const storeDir = path.resolve(userHome, ".wss-cli-dev", "template", "node_modules")
    const { npmName, version } = templateInfo
    this.templateInfo = templateInfo;
    const templateNpm = new Package({
      targetPath,
      storeDir,
      packageName: npmName,
      packageVersion: version
    })
    if (!await templateNpm.exists()) {
      const spinner = new spinnerStart("正在下载模版...")
      // 安装
      await sleep()
      try {
        await templateNpm.install()
      } catch (error) {
        throw error
      } finally {
        spinner.stop(true);
        if (await templateNpm.exists()) {
          log.success('下载模板成功');

          this.templateNpm = templateNpm;
        }
      }
    } else {
      const spinner = new spinnerStart("正在更新模版...")
      await sleep()
      try {
        console.log(templateNpm);
        await templateNpm.update()
      } catch (error) {
        throw error
      } finally {
        spinner.stop(true);
        if (await templateNpm.exists()) {
          log.success('更新模板成功');
          this.templateNpm = templateNpm;
        }
      }
    }
    // console.log(targetPath, storeDir, templateNpm);
    // 
    // 
    // 
  }
  async installTemplate() {
    if (this.templateInfo) {
      if (!this.templateInfo.type) {
        this.templateInfo.type = TEMPLATE_TYPE_NORMAL
      }
      if (this.templateInfo.type === TEMPLATE_TYPE_NORMAL) {
        // 执行标准安装
        await this.installNomalTemplate()
      } else if (this.templateInfo.type === TEMPLATE_TYPE_CUSTOM) {
        // 执行自定义安装
        await this.installCustomTemplate()
      } else {
        throw new Error('无法识别项目模板类型！');
      }
    } else {
      throw new Error('项目模板信息不存在！');
    }
  }
  // 标准安装
  async installNomalTemplate() {
    log.verbose('templateNpm', this.templateNpm);
    let spinner = spinnerStart("正在安装模版..")
    await sleep();
    // 拷贝模板代码至当前目录
    try {
      const templatePath = path.resolve(this.templateNpm.cacheFilePath,
        `node_modules/${this.templateNpm.packageName}/template`);
      const targetPath = process.cwd();
      fse.ensureDirSync(templatePath);
      fse.ensureDirSync(targetPath);
      fse.copySync(templatePath, targetPath)
    } catch (error) {
      throw error
    } finally {
      spinner.stop(true);
      log.success('模板安装成功');
    }
    // ejs 模版渲染
    const templateIgnore = this.templateInfo.ignore || [];
    const ignore = ['**/node_modules/**', ...templateIgnore];
    await this.ejsRender({ ignore })
    const { installCommand, startCommand } = this.templateInfo
    await this.execCommand(installCommand, "依赖安装失败！")
    await this.execCommand(startCommand, "依赖安装失败！")
  }
  checkCommand(cmd) {
    if (WHITE_COMMAND.includes(cmd)) {
      return cmd;
    }
    return null;
  }
  // 依赖安装
  async execCommand(command, errMsg) {
    let ret;
    if (command) {
      const cmdArray = command.split(' ');
      const cmd = this.checkCommand(cmdArray[0]);
      if (!cmd) {
        throw new Error('命令不存在！命令：' + command);
      }
      const args = cmdArray.slice(1);
      ret = await execAsync(cmd, args, {
        stdio: 'inherit',
        cwd: process.cwd(),
      });
    }
    if (ret !== 0) {
      throw new Error(errMsg);
    }
    return ret;
  }

  async ejsRender(options) {
    const dir = process.cwd();
    const projectInfo = this.projectInfo;
    return new Promise((resolve, reject) => {
      glob('**', {
        cwd: dir,
        ignore: options.ignore || '',
        nodir: true,
      }, function (err, files) {
        if (err) {
          reject(err);
        }
        Promise.all(files.map(file => {
          const filePath = path.join(dir, file);
          return new Promise((resolve1, reject1) => {
            ejs.renderFile(filePath, projectInfo, {}, (err, result) => {
              if (err) {
                reject1(err);
              } else {
                fse.writeFileSync(filePath, result);
                resolve1(result);
              }
            });
          });
        })).then(() => {
          resolve();
        }).catch(err => {
          reject(err);
        });
      });
    });
  }
  // 自定义安装
  async installCustomTemplate() { }

  createTemplateChoice() {
    return this.template.map(item => ({
      value: item.npmName,
      name: item.name,
    }));
  }
}

function init(argv) {
  return new InitCommand(argv)
}
module.exports = init
module.exports.InitCommand = InitCommand